
import de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.text.AttributeSet;
import javax.swing.text.AttributeSet.ColorAttribute;
import javax.swing.text.BadLocationException;

/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
/**
 *
 * @author ronaldo
 */
public class DesignClient extends javax.swing.JFrame {

    //Variables de Cliente de Comunicacion
    private ObjectOutputStream salida;
    private ObjectInputStream entrada;
    private String mensaje = "";
    private String servidorChat;
    private Socket cliente;
    //Tray ICON
    private SystemTray tray;
    private final TrayIcon trayIcon;

    /**
     * Creates new form DesignClient
     */
    public DesignClient(String HostConexion) {
        initComponents();

        setSyntheticaBlueMoonLF();
        servidorChat = HostConexion; // establecer el servidor al que se va a conectar este cliente
        this.txtStatus.setText("Intentando Conectar a Servidor");
        Thread HCarpeta = new Thread(new Runnable() {

            public void run() {
                ejecutarCliente();
                //SMessage("hilo", "hilo");
            }
        });

        HCarpeta.start();
        Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/empathy.png"));
        trayIcon = new TrayIcon(image, "Software Comunicacion", null);
        InitIcon();
    }

    private void InitIcon() {
        trayIcon.setToolTip("Departamento de Sistema - Ronaldo Tinoco - Software Comunicacion");
        tray = SystemTray.getSystemTray();
        trayIcon.setImageAutoSize(true);
        AsigEvent();
        try {
            tray.add(trayIcon);
            //trayIcon.displayMessage("Welcome", "Bienvenido", TrayIcon.MessageType.INFO);
        } catch (AWTException e) {
            System.err.println("No se pudo agregar el ícono a la barra tray");
        }
    }

    private void AsigEvent() {
        MouseListener mouseListener = new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
                if (e.getClickCount() == 2) {
                    setVisible(true);
                }
                if (e.getClickCount() == 2) {
                    SMessage("Exit", "Saliendo del sistema");
                    JOptionPane.showMessageDialog(null, "Saliendo del sistema de Comunicacion", "Ha optado por salir del sistema", JOptionPane.INFORMATION_MESSAGE);
                    System.exit(0);
                }
            }

            @Override
            public void mousePressed(MouseEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void mouseExited(MouseEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }
        };
        trayIcon.addMouseListener(mouseListener);
    }

    private void SMessage(String Title, String Content) {
        if (!this.getFocusableWindowState()) {
            trayIcon.displayMessage(Title, Content, TrayIcon.MessageType.INFO);
        }
    }

    private void setSyntheticaBlueMoonLF() {
        try {
            UIManager.setLookAndFeel(new SyntheticaBlackStarLookAndFeel());
            SwingUtilities.updateComponentTreeUI(this);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    Timer TimeTs;

    // conectarse al servidor y procesar mensajes del servidor
    private void ejecutarCliente() {
        // conectarse al servidor, obtener flujos, procesar la conexi�n
        try {
            conectarAServidor(); // Paso 1: crear un socket para realizar la conexi�n
            obtenerFlujos();      // Paso 2: obtener los flujos de entrada y salida
            procesarConexion(); // Paso 3: procesar la conexi�n
        } // el servidor cerr� la conexi�n
        catch (EOFException excepcionEOF) {
            establecerCampoTextoEditable(false);
            mostrarMensaje("\nEl cliente termino la conexion\n\n");
            mostrarMensaje("Intentando realizar conexion...\n");
//            try {
//                //areaPantalla.setText("");
//                Thread.sleep(500);
//            } catch (InterruptedException ex) {
//                //Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
//            }
            ejecutarCliente();
        } // procesar los problemas que pueden ocurrir al comunicarse con el servidor
        catch (IOException excepcionES) {
            //areaPantalla.setText("");
//            try {
//                //areaPantalla.setText("");
//                Thread.sleep(1000);
//            } catch (InterruptedException ex) {
//                //Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
//            }
            ejecutarCliente();
            //excepcionES.printStackTrace();
        } finally {
            cerrarConexion(); // Paso 4: cerrar la conexi�n
        }

    } // fin del m�todo ejecutarCliente

    // conectarse al servidor
    private void conectarAServidor() throws IOException {
        mostrarMensaje(".");
        // crear Socket para realizar la conexi�n con el servidor
        cliente = new Socket(InetAddress.getByName(servidorChat), 12345);

        // mostrar la informaci�n de la conexi�n
        mostrarMensaje("Conectado a: "
                + cliente.getInetAddress().getHostName() + "\n");
        this.JPStatus.setVisible(false);
    }

    // obtener flujos para enviar y recibir datos
    private void obtenerFlujos() throws IOException {
        // establecer flujo de salida para los objetos
        salida = new ObjectOutputStream(cliente.getOutputStream());
        salida.flush(); // vac�ar b�fer de salida para enviar informaci�n de encabezado

        // establecer flujo de entrada para los objetos
        entrada = new ObjectInputStream(cliente.getInputStream());

        mostrarMensaje("Se recibieron los flujos de E/S\n");
    }

    // procesar la conexi�n con el servidor
    private void procesarConexion() throws IOException {
        // habilitar campoIntroducir para que el usuario del cliente pueda enviar mensajes
        establecerCampoTextoEditable(true);

        do { // procesar mensajes enviados del servidor

            // leer mensaje y mostrarlo en pantalla
            try {
                mensaje = (String) entrada.readObject();
                txtConsole.setText(mensaje);
                AppendText(txtConsole.getText().length(), "\n" + mensaje);
                //mostrarMensaje("\n" + mensaje);
                StringBuilder x = new StringBuilder(mensaje);
                x.setLength(20);
                //trayIcon.displayMessage("Ha recibido un Mensaje del Servidor",x.toString().trim()+"...", TrayIcon.MessageType.INFO);
                trayIcon.displayMessage("Ha recibido un Mensaje del Servidor", "Ha recibido un Mensaje del servidor", TrayIcon.MessageType.INFO);
            } // atrapar los problemas que pueden ocurrir al leer del servidor
            catch (ClassNotFoundException excepcionClaseNoEncontrada) {
                mostrarMensaje("Se recibio un objeto de tipo desconocido");
            } catch (Exception e) {
                JOptionPane.showMessageDialog(this, "Contenido");
            }

        } while (!mensaje.equals("SERVIDOR>>> TERMINAR"));

    } // fin del m�todo procesarConexion

    // cerrar flujos y socket
    private void cerrarConexion() {
        //mostrarMensaje( "\nCerrando conexi�n" );
        establecerCampoTextoEditable(false); // deshabilitar campoIntroducir

        try {
            salida.close();
            entrada.close();
            cliente.close();
        } catch (IOException excepcionES) {
            //excepcionES.printStackTrace();
        }
    }

    // enviar mensaje al servidor
    private void enviarDatos(String mensaje) {
        // enviar objeto al servidor
        try {
            salida.writeObject("MAR>>> " + mensaje);
            salida.flush();
            // mostrarMensaje("\nMAR>>> " + mensaje);
        } // procesar los problemas que pueden ocurrir al enviar el objeto
        catch (IOException excepcionES) {
            AppendText(txtConsole.getText().length(), "\nError al escribir el objeto");
        }
    }

    // m�todo utilitario que es llamado desde otros subprocesos para manipular a 
    // areaPantalla en el subproceso despachador de eventos
    private void mostrarMensaje(final String mensajeAMostrar) {
        // mostrar mensaje del subproceso de ejecuci�n de la GUI
        AppendText(txtConsole.getText().length(), mensajeAMostrar);
        txtConsole.setCaretPosition(txtConsole.getText().length());
//        SwingUtilities.invokeLater(
//                new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
//
//                    public void run() // actualiza areaPantalla
//                    {
//                        AppendText(txtConsole.getText().length(), mensajeAMostrar);
//                        txtConsole.setCaretPosition(txtConsole.getText().length());
//                    }
//                } // fin de la clase interna
//                ); // fin de la llamada a SwingUtilities.invokeLater
    }

    // m�todo utilitario que es llamado desde otros subprocesos para manipular a 
    // campoIntroducir en el subproceso despachador de eventos
    private void establecerCampoTextoEditable(final boolean editable) {
        // mostrar mensaje del subproceso de ejecuci�n de la GUI
        SwingUtilities.invokeLater(
                new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente

                    public void run() // establece la capacidad de modificar campoIntroducir
                    {
                        txtComunication.setEditable(editable);
                    }
                } // fin de la clase interna
                ); // fin de la llamada a SwingUtilities.invokeLater
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        JPStatus = new javax.swing.JPanel();
        txtStatus = new javax.swing.JTextField();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtComunication = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        txtConsole = new javax.swing.JTextPane();
        jPanel3 = new javax.swing.JPanel();

        setTitle("Comunication");
        setAlwaysOnTop(true);
        setLocationByPlatform(true);

        JPStatus.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Cliente Comunicación - Status", javax.swing.border.TitledBorder.LEFT, javax.swing.border.TitledBorder.TOP, new java.awt.Font("DejaVu Serif Condensed", 1, 12), new java.awt.Color(231, 127, 24))); // NOI18N

        txtStatus.setEditable(false);

        javax.swing.GroupLayout JPStatusLayout = new javax.swing.GroupLayout(JPStatus);
        JPStatus.setLayout(JPStatusLayout);
        JPStatusLayout.setHorizontalGroup(
            JPStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(JPStatusLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(txtStatus)
                .addContainerGap())
        );
        JPStatusLayout.setVerticalGroup(
            JPStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(JPStatusLayout.createSequentialGroup()
                .addComponent(txtStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 14, Short.MAX_VALUE))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Contenido", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Serif Condensed", 1, 12), new java.awt.Color(233, 50, 3))); // NOI18N

        txtComunication.setColumns(5);
        txtComunication.setEditable(false);
        txtComunication.setLineWrap(true);
        txtComunication.setRows(2);
        txtComunication.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                txtComunicationKeyTyped(evt);
            }
        });
        jScrollPane1.setViewportView(txtComunication);

        txtConsole.setContentType("html");
        txtConsole.setEditable(false);
        jScrollPane2.setViewportView(txtConsole);

        jPanel3.setBackground(new java.awt.Color(255, 163, 0));
        jPanel3.setPreferredSize(new java.awt.Dimension(0, 5));

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 5, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2)
                    .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 209, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 209, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2)
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(JPStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(JPStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void txtComunicationKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtComunicationKeyTyped
        // TODO add your handling code here:
        if (evt.getKeyChar() == java.awt.event.KeyEvent.VK_ENTER) {
            if (this.txtComunication.getText().trim().length() > 0) {
                AppendText(this.txtConsole.getText().length(), "\nYOP=" + this.txtComunication.getText().replace("\n", "").trim());
                enviarDatos(this.txtComunication.getText().replace("\n", "").trim());
            }
            this.txtComunication.setText("");
        }
    }//GEN-LAST:event_txtComunicationKeyTyped

    private void AppendText(int pos, String Text) {
        try {
            this.txtConsole.getDocument().insertString(pos, Text, null);
        } catch (BadLocationException ex) {
            // Logger.getLogger(DesignClient.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(final String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;


                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(DesignClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(DesignClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(DesignClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(DesignClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                if (args.length == 0) {
                    new DesignClient("192.168.5.28").setVisible(true);
                } else {
                    new DesignClient(args[0]).setVisible(true);
                }
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel JPStatus;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTextArea txtComunication;
    private javax.swing.JTextPane txtConsole;
    private javax.swing.JTextField txtStatus;
    // End of variables declaration//GEN-END:variables
}
